// Main header
#include "../Main.h"

// My header
#include "Controller_Screen_Editor.h"

// Fridge
#include "Controller_Main.h"
#include "Controller_ModalAddWidgetDialog.h"
#include "Controller_ModalColourPickerDialog.h"
#include "../FileTools.h"
#include "../Preset/Element.h"
#include "../Preset/Preset.h"
#include "../Preset/ExposedVariable.h"
#include "../StringHash.h"
#include "../SuperTree.h"
#include "../TypedList.h"
#include "../Widgets/Button.h"
#include "../Widgets/CodeEditor.h"
#include "../Widgets/ColourWell.h"
#include "../Widgets/MenuBar.h"
#include "../Widgets/Slider.h"
#include "../Widgets/TabPages.h"
#include "../Widgets/Tickbox.h"
#include "../Widgets/TextEditor.h"
#include "../Widgets/TreeView.h"
#include "../Widgets/TreeEditor.h"
#include "../Visuals/Visuals_Main.h"

bool					Controller_Screen_Editor::s_bVisible					= false;
bool					Controller_Screen_Editor::s_bNeedToUpdateControls		= true;
bool					Controller_Screen_Editor::s_bShowingElementTabs			= false;
bool					Controller_Screen_Editor::s_bElement_IsGroup			= false;
bool					Controller_Screen_Editor::s_bElement_IsUILocked			= false;
TreeEditor*				Controller_Screen_Editor::s_pxTreeEditor				= 0;
CodeEditor*				Controller_Screen_Editor::s_pxCodeEditor				= 0;
TextEditor*				Controller_Screen_Editor::s_pxScriptOutput				= 0;
TabPages*				Controller_Screen_Editor::s_pxElementTabs				= 0;
Panel*					Controller_Screen_Editor::s_pxControlTab				= 0;
Panel*					Controller_Screen_Editor::s_pxAdvancedTab				= 0;
Panel*					Controller_Screen_Editor::s_pxControlPanel				= 0;
Tickbox*				Controller_Screen_Editor::s_pxUILockTickbox				= 0;
Button*					Controller_Screen_Editor::s_pxAddWidgetButton			= 0;
u_int					Controller_Screen_Editor::s_uUserWidgetVerticalPos		= 0;	

//FHandle				Controller_Screen_Editor::s_xSelectedElement	= -1;


TextEditor* Controller_Screen_Editor::s_pxElementNameBox = 0;


static const u_int uMENU_BAR_HEIGHT = 24;
static const u_int uTREEVIEW_WIDTH = 200;
static const u_int uTREEEDITOR_WIDTH = 320;
static const u_int uDIVIDER_WIDTH = 8;
static const u_int uDIVIDER_COLOUR = 0xDDDDDDFF;
static const u_int uEMPTYSPACE_COLOUR = 0xEEEEEEFF;
static const u_int uEMPTYSPACE_MARGIN = 8;
static const u_int uSHADOW_COLOUR = 0xCCCCCCFF;
static const u_int uSHADOW_MARGIN = 5;


u_int GetLineColourForScriptOutput( const char* szText )
{
	if( !szText )
	{
		return 0;
	}
	if( szText[0] == '~' )
	{
		return 0x057F17FF;
	}
	if( szText[0] == '!' )
	{
		return 0xFF283EFF;
	}
	return 0x222222FF;
}

// Template list functions

bool Controller_Screen_Editor::TemplateList_BeginDragDrop( DragDropData* pxData, Widget* pxCaller )
{
	pxData->SetID( GetStringHash("Template") );
	pxData->SetIcon( GetStringHash("StarDrop32") );
	
	// We know this is a button with FFileInfo user data
	Button* pxButton = reinterpret_cast< Button* >( pxCaller );
	
	void* pData = 0;
	u_int uDataSize = 0;
	pxButton->GetUserData( pData, uDataSize );
	
	FFileInfo* pxFFileInfo = reinterpret_cast<FFileInfo*>( pData );
	
	if( pxFFileInfo->IsDirectory() )
	{
		return false;
	}
	
	pxData->SetData( pxFFileInfo, sizeof( FFileInfo ) );
	
	return true;
}

// Preset editor functions

bool Controller_Screen_Editor::Preset_DragOverCallback( const DragDropData* pxData, Widget* pxCaller )
{
	if( pxData->GetID() == GetStringHash("Template") )
	{
		FHandle iEntry = s_pxTreeEditor->GetEntryUnderCursor();
		if( iEntry == INVALID_HANDLE )
		{
			s_pxTreeEditor->SetInsertionMarker( s_pxTreeEditor->GetLastEntry() );
		}
		else
		{
			s_pxTreeEditor->SetInsertionMarker( iEntry );
		}
		
		return true;
	}
	return false;
}

void Controller_Screen_Editor::Preset_EndDragDropCallback( const DragDropData* pxData, Widget* pxCaller )
{
	// Add an element to the preset and update the tree editor control
	const void* pData;
	u_int uDataSize;
	
	pxData->GetData( pData, uDataSize );
	
	const FFileInfo* pxFFileInfo = reinterpret_cast< const FFileInfo* >( pData );
	
	Preset* pxPreset = Controller_Main::GetCurrentPreset();
	FHandle xElementHandle = pxPreset->CreateElement( pxFFileInfo, TREE_HANDLE_HEAD );
	Element* pxElement = pxPreset->GetElement( xElementHandle );
	FAssert( pxElement != 0 );

	// Work out the parent and insert point. 
	// If the insert marker is on a group then put it in the group, otherwise just put it after

	FHandle xInsertionMarker = s_pxTreeEditor->GetInsertionMarker();
	
	FHandle xParentHandle = INVALID_HANDLE;
	FHandle xInsertAfter = xInsertionMarker;
		
	if( xInsertionMarker != INVALID_HANDLE )
	{
		Element* pxInsertElement = pxPreset->GetElement( xInsertionMarker );
		if( pxInsertElement && pxInsertElement->IsGroup() )
		{
			xParentHandle = xInsertionMarker;
			xInsertAfter = INVALID_HANDLE;
		}
	}

	// Put the element in the right place

	pxPreset->MoveElement( xElementHandle, xParentHandle, xInsertAfter );
	
	// Add to the tree editor control, use the same FHandle so that we have a mapping from preset to interface

	s_pxTreeEditor->InsertTreeItem( pxElement->GetName(), xElementHandle );
	s_pxTreeEditor->MoveTreeItem( xElementHandle, xParentHandle, xInsertAfter );
	s_pxTreeEditor->ClearInsertionMarker();
	
	TreeEditorEntry* pxEntry = s_pxTreeEditor->GetTreeItem( xElementHandle );
	pxEntry->SetUserCanDelete( true );
	pxEntry->SetUserCanDuplicate( true );
	if( pxElement->IsGroup() )
	{
		pxEntry->SetImage( GetStringHash( "StarStack32" ) );
		pxEntry->SetIsContainer( true );
	}
	else
	{
		pxEntry->SetImage( GetStringHash( "Star32" ) );
	}
	s_pxTreeEditor->SetSelection( xElementHandle );

	// Restart the preset

	pxPreset->Restart();
}

void Controller_Screen_Editor::Preset_OnSelection( FHandle xHandle )
{
	// Show the contents of the selected element in the code window
	Preset* pxPreset = Controller_Main::GetCurrentPreset();
	if( pxPreset )
	{
		Element* pxElement = pxPreset->GetElement( xHandle );
		
		if( pxElement )
		{
			s_bNeedToUpdateControls = true;
			s_bElement_IsGroup = pxElement->IsGroup();
			s_bElement_IsUILocked = pxElement->GetIsUILocked();
			
			// Add the element tabs if they don't exist yet
			if( !s_bShowingElementTabs )
			{
				Panel* pxPanel = new Panel( Controller_Main::GetWindowPanel() );
				pxPanel->SetPosition( uTREEVIEW_WIDTH + uDIVIDER_WIDTH + uTREEEDITOR_WIDTH + 1, uMENU_BAR_HEIGHT );
				pxPanel->SetSize( uDIVIDER_WIDTH - 2, Controller_Main::GetHeight() );
				pxPanel->SetAnchors( ANCHOR_TOP | ANCHOR_BOTTOM | ANCHOR_LEFT );
				pxPanel->SetColour( uDIVIDER_COLOUR );
								
				s_pxElementTabs = new TabPages( Controller_Main::GetWindowPanel() );
				s_pxElementTabs->SetPosition( pxPanel->GetOriginalX() + pxPanel->GetOriginalWidth(), uMENU_BAR_HEIGHT );
				s_pxElementTabs->SetSize( Controller_Main::GetWidth() - ( pxPanel->GetOriginalX() + pxPanel->GetOriginalWidth() ), Controller_Main::GetHeight() - uMENU_BAR_HEIGHT );
				s_pxElementTabs->SetAnchors( ANCHOR_TOP | ANCHOR_BOTTOM | ANCHOR_LEFT | ANCHOR_RIGHT );
				s_pxElementTabs->SetColour( uDIVIDER_COLOUR );
				
				// Make other tabs
				FHandle iTabHandle = s_pxElementTabs->AddTab( "Code" );
				Panel* pxTabPage = s_pxElementTabs->GetTabPanel( iTabHandle );
				PopulateCodeTab( pxTabPage );
				
				// TODO: This should go before code, it's just second in the tabs for convenience during development
				iTabHandle = s_pxElementTabs->AddTab( "Controller" );
				s_pxControlTab = s_pxElementTabs->GetTabPanel( iTabHandle );
				
				iTabHandle = s_pxElementTabs->AddTab( "Advanced" );
				s_pxAdvancedTab = s_pxElementTabs->GetTabPanel( iTabHandle );
				PopulateAdvancedTab( s_pxAdvancedTab );
				
				s_bShowingElementTabs = true;
			}
			
			// Always repopulate control tab
			PopulateControlTab( s_pxControlTab );
			
			s_pxCodeEditor->SetText( pxElement->GetCodeString() );
			s_pxCodeEditor->SetModified( false );
			
			if( s_pxElementNameBox )
			{
				s_pxElementNameBox->SetText( pxElement->GetName() );
				s_pxElementNameBox->SetModified( false );
			}
		}
	}
}

void Controller_Screen_Editor::Preset_OnDelete( FHandle xHandle )
{
	Preset* pxPreset = Controller_Main::GetCurrentPreset();
	pxPreset->RemoveElement( xHandle );
}

// Controller Screen editor functions

void Controller_Screen_Editor::Show ()
{	
	if( s_bVisible )
	{
		return;
	}
	
	MenuBar* pxMenuBar = new MenuBar( Controller_Main::GetWindowPanel() );
	pxMenuBar->SetPosition( 0, 0 );
	pxMenuBar->SetSize( MIN_SCREEN_WIDTH, uMENU_BAR_HEIGHT );
	pxMenuBar->SetAnchors( ANCHOR_TOP | ANCHOR_LEFT | ANCHOR_RIGHT );
	pxMenuBar->SetColour( uDIVIDER_COLOUR );
	
	PopulateMenuBar( pxMenuBar );
	
	// Generate the list of effects, this is just a tree of files on disc
	SuperTree<FFileInfo>* pxTemplateFileList = new SuperTree<FFileInfo>( true );
	
	FileTools::FindFiles( pxTemplateFileList, FRIDGE_FILE_TEMPLATE );
	
	// Template browser
	
	TreeView* pxTreeView = new TreeView( Controller_Main::GetWindowPanel() );
	pxTreeView->SetPosition( 0, uMENU_BAR_HEIGHT );
	pxTreeView->SetSize( uTREEVIEW_WIDTH, MIN_SCREEN_HEIGHT );
	pxTreeView->SetAnchors( ANCHOR_TOP | ANCHOR_BOTTOM | ANCHOR_LEFT );
	
	pxTreeView->SetDefaultBeginDragDropCallback( TemplateList_BeginDragDrop );
	pxTreeView->PopulateFromFileTree( pxTemplateFileList );
	
	delete pxTemplateFileList;
	pxTemplateFileList = 0;
	
	// Divider
	
	Panel* pxPanel = new Panel( Controller_Main::GetWindowPanel() );
	pxPanel->SetPosition( uTREEVIEW_WIDTH + 1, uMENU_BAR_HEIGHT );
	pxPanel->SetSize( uDIVIDER_WIDTH - 2, MIN_SCREEN_HEIGHT );
	pxPanel->SetAnchors( ANCHOR_TOP | ANCHOR_BOTTOM | ANCHOR_LEFT );
	pxPanel->SetColour( uDIVIDER_COLOUR );
	
	// Preset tree

	s_pxTreeEditor = new TreeEditor( Controller_Main::GetWindowPanel() );
	s_pxTreeEditor->SetPosition( uTREEVIEW_WIDTH + uDIVIDER_WIDTH, uMENU_BAR_HEIGHT );
	s_pxTreeEditor->SetSize( uTREEEDITOR_WIDTH, MIN_SCREEN_HEIGHT );
	s_pxTreeEditor->SetAnchors( ANCHOR_TOP | ANCHOR_BOTTOM | ANCHOR_LEFT );
	s_pxTreeEditor->SetDragOverCallback( Preset_DragOverCallback );
	s_pxTreeEditor->SetEndDragDropCallback( Preset_EndDragDropCallback );
	s_pxTreeEditor->SetOnSelectionCallback( Preset_OnSelection );
	s_pxTreeEditor->SetOnDeleteCallback( Preset_OnDelete );
	
	s_bVisible = true;
}

void Controller_Screen_Editor::Control_Panel_ButtonAddWidget( void* pUserData )
{
    Controller_ModalAddWidgetDialog::SetCallback( DialogCallback_AddWidget );
    Controller_ModalAddWidgetDialog::Show();
}

void Controller_Screen_Editor::DialogCallback_AddWidget( const Controller_ModalDialogResult eType )
{
	if ( eType == DIALOGRESULT_OK ) 
	{
		EXPOSED_VARIABLE_TYPE xControlType = Controller_ModalAddWidgetDialog::s_xControlType;
		
		ExposedVariable* pxExposedVariable = new ExposedVariable();
		pxExposedVariable->SetValue( 0.0f );
		pxExposedVariable->SetName( Controller_ModalAddWidgetDialog::s_szName );
		pxExposedVariable->SetVariableType( xControlType );
		pxExposedVariable->SetShowLabel( Controller_ModalAddWidgetDialog::s_bShowLabel );
		
		// Extra parameters 
		switch( xControlType )
		{
			case EXPOSED_VARIABLE_SLIDER:
			{
				pxExposedVariable->SetVariableType( EXPOSED_VARIABLE_SLIDER );
			}
			break;
	
			case EXPOSED_VARIABLE_COLOUR:
			{
				pxExposedVariable->SetVariableType( EXPOSED_VARIABLE_COLOUR );
			}
			break;
		}
		
		Preset* pxPreset = Controller_Main::GetCurrentPreset();
		Element* pxElement = pxPreset->GetElement( s_pxTreeEditor->GetSelection() );
		pxElement->AddExposedVariable( pxExposedVariable );
		
		s_bNeedToUpdateControls = true;
	}
}

void Controller_Screen_Editor::PopulateCodeTab( Panel* pxPanel )
{
	FAssert( pxPanel != 0 );
	
	pxPanel->DeleteChildren();
	
	const u_int uScriptOutputHeight = 128;
	const u_int uTabPageTop = pxPanel->GetOriginalY();
	const u_int uTabPageBottom = pxPanel->GetOriginalY() + pxPanel->GetOriginalHeight();
	
	s_pxScriptOutput = new TextEditor( pxPanel );
	s_pxScriptOutput->SetPosition( pxPanel->GetOriginalX() + uEMPTYSPACE_MARGIN ,  uTabPageBottom - ( uEMPTYSPACE_MARGIN + uScriptOutputHeight ) );
	s_pxScriptOutput->SetSize( pxPanel->GetOriginalWidth() - uEMPTYSPACE_MARGIN * 2, uScriptOutputHeight );
    s_pxScriptOutput->SetAnchors( ANCHOR_BOTTOM | ANCHOR_LEFT | ANCHOR_RIGHT );
	s_pxScriptOutput->SetHasBorder( true );
	s_pxScriptOutput->SetBorderWidth( 1.0f );
	s_pxScriptOutput->SetReadOnly( true );
	s_pxScriptOutput->SetTextLineColourCallback( GetLineColourForScriptOutput );
	
    s_pxCodeEditor = new CodeEditor( pxPanel );
	s_pxCodeEditor->SetPosition( pxPanel->GetOriginalX() + uEMPTYSPACE_MARGIN , uTabPageTop + uEMPTYSPACE_MARGIN );
	s_pxCodeEditor->SetSize( pxPanel->GetOriginalWidth() - uEMPTYSPACE_MARGIN * 2, pxPanel->GetOriginalHeight() - ( uEMPTYSPACE_MARGIN * 3 + uScriptOutputHeight ) );
    s_pxCodeEditor->SetAnchors( ANCHORS_ALL );
	s_pxCodeEditor->SetHasBorder( true );
	s_pxCodeEditor->SetBorderWidth( 1.0f );
	s_pxCodeEditor->SetShowScrollBars( true, true );
}

void Controller_Screen_Editor::PopulateControlTab( Panel* pxPanel )
{
	FAssert( pxPanel != 0 );
	
	pxPanel->DeleteChildren();
	
	const u_int uHorzPos = pxPanel->GetOriginalX() + 8;
	u_int uVerticalPos = pxPanel->GetOriginalY() + 8;
	u_int uButtonHeight = 24;
	
	if( s_bElement_IsUILocked )
	{
		uButtonHeight = 0;
		uButtonHeight -= uEMPTYSPACE_MARGIN;
	}
	
	// Control sub-panel
	s_pxControlPanel = new Panel( pxPanel );
	s_pxControlPanel->SetPosition( uHorzPos, uVerticalPos + uButtonHeight + uEMPTYSPACE_MARGIN );
	s_pxControlPanel->SetSize( pxPanel->GetOriginalWidth() - uEMPTYSPACE_MARGIN * 2, pxPanel->GetOriginalHeight() - ( uEMPTYSPACE_MARGIN * 3 + uButtonHeight ) );
	s_pxControlPanel->SetHasBorder( true );
	s_pxControlPanel->SetBorderWidth( 1.0f );
	s_pxControlPanel->SetAnchors( ANCHORS_ALL );
	
	if( !s_bElement_IsUILocked )
	{
		// Buttons for widget-adding
		s_pxAddWidgetButton = new Button( pxPanel );
		s_pxAddWidgetButton->SetSize( 100, uButtonHeight );
		s_pxAddWidgetButton->SetLabel( "Add Control" );
		s_pxAddWidgetButton->SetEnabled( true );
		s_pxAddWidgetButton->SetPosition( uHorzPos , uVerticalPos ); 
		s_pxAddWidgetButton->SetButtonPressCallback( Control_Panel_ButtonAddWidget, 0 );
	}
	
	s_bNeedToUpdateControls = true;
}

void Controller_Screen_Editor::PopulateAdvancedTab( Panel* pxPanel )
{
	FAssert( pxPanel != 0 );
	
	pxPanel->DeleteChildren();
	
	const u_int uHorzPos = pxPanel->GetOriginalX() + 8;
	u_int uVerticalPos = pxPanel->GetOriginalY() + 8;
	
	StaticText* pxText = new StaticText( pxPanel );
	pxText->SetText( "Name" );
	pxText->SetPosition( uHorzPos, uVerticalPos );
	uVerticalPos += 16;
	
	s_pxElementNameBox = new TextEditor( pxPanel );
	s_pxElementNameBox->SetPosition( uHorzPos, uVerticalPos );
	s_pxElementNameBox->SetSize( pxPanel->GetOriginalWidth() - 8 * 2, 24 );
	s_pxElementNameBox->SetHasBorder( true );
	s_pxElementNameBox->SetBorderWidth( 1.0f );
	s_pxElementNameBox->SetSingleLine( true );
	s_pxElementNameBox->SetLengthLimit( 100 );

	uVerticalPos += 40;
	
	Tickbox* pxTickbox = new Tickbox( pxPanel );
	pxTickbox->SetPosition( uHorzPos, uVerticalPos );
	pxTickbox->SetLabel( "Element Group" );
	pxTickbox->SetBool( &s_bElement_IsGroup );
	
	uVerticalPos += 30;
	
	s_pxUILockTickbox = new Tickbox( pxPanel );
	s_pxUILockTickbox->SetPosition( uHorzPos, uVerticalPos );
	s_pxUILockTickbox->SetLabel( "Lock Control Panel" );
	s_pxUILockTickbox->SetBool( &s_bElement_IsUILocked );
}

void Controller_Screen_Editor::PopulateMenuBar( MenuBar* pxMenuBar )
{
	FAssert( pxMenuBar != 0 );
	
	if( !pxMenuBar )
	{
		return;
	}
	
	FHandle iMenu = INVALID_HANDLE;
	
	iMenu = pxMenuBar->AddMenu( "Fridge" );
	pxMenuBar->AddMenuItem( iMenu, "New Project", Menu_Fridge_New, 0 );
	pxMenuBar->AddMenuItem( iMenu, "Open Project", Menu_Fridge_Open, 0 );
	pxMenuBar->AddDivider( iMenu );
	pxMenuBar->AddMenuItem( iMenu, "Save Project", Menu_Fridge_Save, 0 );
	pxMenuBar->AddMenuItem( iMenu, "Save Project As...", Menu_Fridge_SaveAs, 0 );
	pxMenuBar->AddDivider( iMenu );
	pxMenuBar->AddMenuItem( iMenu, "Main Menu", Menu_Fridge_MainMenu, 0 );
	pxMenuBar->AddMenuItem( iMenu, "Quit", Menu_Fridge_Quit, 0 );
	
	iMenu = pxMenuBar->AddMenu( "Edit" );
	pxMenuBar->AddMenuItem( iMenu, "Cut", 0, 0 );
	pxMenuBar->AddMenuItem( iMenu, "Copy", 0, 0 );
	pxMenuBar->AddMenuItem( iMenu, "Paste", 0, 0 );
	
	iMenu = pxMenuBar->AddMenu( "Preset" );
	pxMenuBar->AddMenuItem( iMenu, "Resource Manager", Menu_Preset_ResourceManager, 0 );
	
	iMenu = pxMenuBar->AddMenu( "Effect" );
	pxMenuBar->AddMenuItem( iMenu, "Save As Template", Menu_Effect_SaveAsTemplate, 0 );
	
	pxMenuBar->AddMenu( "Help" );
}

void Controller_Screen_Editor::Hide ()
{
	if( !s_bVisible )
	{
		return;
	}
	
	s_bVisible = false;
}

void Controller_Screen_Editor::Update()
{
	bool bDeleteTabs = false;
	
	if( s_pxTreeEditor )
	{
		// Get preset
		Preset* pxPreset = Controller_Main::GetCurrentPreset();
		if( pxPreset )
		{
			// Get selected element
			Element* pxElement = pxPreset->GetElement( s_pxTreeEditor->GetSelection() );
			if( pxElement )
			{				
				bool bAnythingModified = false;

				// Check code editor for updates
				if( s_pxCodeEditor && s_pxCodeEditor->IsModified() )
				{
					pxElement->SetCodeString( s_pxCodeEditor->GetText() );
					s_pxCodeEditor->SetModified( false );
					bAnythingModified = true;
				}

				if( s_bElement_IsGroup != pxElement->IsGroup() )
				{
					pxElement->SetIsGroup( s_bElement_IsGroup );
					bAnythingModified = true;
				}
				
				if( s_bElement_IsUILocked != pxElement->GetIsUILocked() )
				{
					pxElement->SetIsUILocked( s_bElement_IsUILocked );
					bAnythingModified = true;
				}
				
				if( s_pxElementNameBox && s_pxElementNameBox->IsModified() )
				{
					pxElement->SetName( s_pxElementNameBox->GetText() );
					s_pxElementNameBox->SetModified( false );
					
					TreeEditorEntry* pxEntry = s_pxTreeEditor->GetTreeItem( s_pxTreeEditor->GetSelection() );
					if( pxEntry )
					{
						pxEntry->SetText( pxElement->GetName() );
					}
					bAnythingModified = true;
				}

				// Remake control panel if the lock tickbox has changed
				if( s_pxUILockTickbox && s_pxUILockTickbox->IsModified() )
				{
					PopulateControlTab( s_pxControlTab );
					s_pxUILockTickbox->SetModified( false );
				}
				   
				// Recreate controls
				if( s_bShowingElementTabs && s_bNeedToUpdateControls )
				{
					s_uUserWidgetVerticalPos = s_pxControlPanel->GetOriginalY() + uEMPTYSPACE_MARGIN;
					
					s_pxControlPanel->DeleteChildren();
					
					for( u_int i = 0; i < (u_int)pxElement->GetNumExposedVariables(); i++ )
					{
						ExposedVariable* pxExposedVariable = pxElement->GetExposedVariable( i );
						if( pxExposedVariable )
						{
							AddExposeControl( pxExposedVariable );
						}
					}
					
					// Done updating
					s_bNeedToUpdateControls = false;
				}
				
				// Check all the user widgets for modifications
				for( u_int i = 0; i < (u_int)pxElement->GetNumExposedVariables(); i++ )
				{
					ExposedVariable* pxExposedVariable = pxElement->GetExposedVariable( i );
					FAssert( pxExposedVariable != 0 );
					
					Widget* pxUserWidget = GetControlByName( pxExposedVariable->GetName() );
					FAssert( pxUserWidget != 0 );
					
					if( pxUserWidget->IsModified() )
					{
						switch( pxExposedVariable->GetVariableType() )
						{
							case EXPOSED_VARIABLE_NUMBER:
							{
								TextEditor* pxUserTextEditorWidget = reinterpret_cast< TextEditor* >( pxUserWidget );
								const char* szValue = pxUserTextEditorWidget->GetText();
								float fValue = 0.0f;
								if ( EOF != sscanf( szValue, "%f", &fValue ) )
								{
									pxExposedVariable->SetValue( fValue );
								}
							
								pxUserTextEditorWidget->SetModified( false );
							}
							break;
							case EXPOSED_VARIABLE_SLIDER:
							{
								Slider* pxUserSliderWidget = reinterpret_cast< Slider* > ( pxUserWidget );
								float fValue = pxUserSliderWidget->GetValue();
								pxExposedVariable->SetValue( fValue );
								
								pxUserSliderWidget->SetModified( false );
							}
							break;
							case EXPOSED_VARIABLE_COLOUR:
							{
								ColourWell* pxUserColourWellWidget = reinterpret_cast< ColourWell* > ( pxUserWidget );
								pxExposedVariable->SetValue( (double)pxUserColourWellWidget->GetValue() );

								pxUserColourWellWidget->SetModified( false );
							}
							break;
						}
						
						bAnythingModified = true;
					}
				}

				if( bAnythingModified )
				{
					pxPreset->Restart();
				}

				if( s_pxScriptOutput )
				{
					s_pxScriptOutput->Clear();
					s_pxScriptOutput->AppendText( pxElement->GetScriptOutput( SCRIPT_OUTPUT_INIT ) );
					s_pxScriptOutput->AppendText( pxElement->GetScriptOutput( SCRIPT_OUTPUT_UPDATE ) );
					s_pxScriptOutput->AppendText( pxElement->GetScriptOutput( SCRIPT_OUTPUT_RENDER ) );
				}
			}
			else
			{
				bDeleteTabs = true;
			}
		}
		else
		{
			// Delete all tabs
			if( s_bShowingElementTabs )
			{
				while( s_pxElementTabs->GetNumTabs() > 0 )
				{
					s_pxElementTabs->DeleteTab( 0 );
				}
				
				// Delete tab page 
				delete s_pxElementTabs;
				s_pxElementTabs = 0;
				
				s_bShowingElementTabs = false;
			}
		}

		if( !s_pxTreeEditor->MouseInWidget() )
		{
			s_pxTreeEditor->ClearInsertionMarker();
		}
		
		if( bDeleteTabs && s_bShowingElementTabs )
		{
			delete s_pxElementTabs;
			s_pxElementTabs = 0;
				
			s_bShowingElementTabs = false;
		}
	}
}

void Controller_Screen_Editor::AddExposeControl( ExposedVariable* pxExposedVariable )
{
	// Don't duplicate controls
	if ( !GetControlByName( pxExposedVariable->GetName() ) ) 
	{
		Panel* pxParentPanel = new Panel( s_pxControlPanel );
		pxParentPanel->SetName( pxExposedVariable->GetName() );
		pxParentPanel->SetPosition( s_pxControlPanel->GetOriginalX(), s_uUserWidgetVerticalPos );
		pxParentPanel->SetAnchors( ANCHORS_ALL_PARENT_RELATIVE );
		
		if( pxExposedVariable->GetShowLabel() )
		{
			s_uUserWidgetVerticalPos += 17;
		}
		
		switch ( pxExposedVariable->GetVariableType() )
		{
			// NUMBER ///////////////////////////////////
			case EXPOSED_VARIABLE_NUMBER: 
			{				
				TextEditor* pxNumberControl = new TextEditor( pxParentPanel );
				pxNumberControl->SetName( pxExposedVariable->GetName() );
				pxNumberControl->SetPosition( s_pxControlPanel->GetOriginalX() + uEMPTYSPACE_MARGIN, s_uUserWidgetVerticalPos );
				pxNumberControl->SetSize( s_pxControlPanel->GetOriginalWidth() - uEMPTYSPACE_MARGIN * 2, 24 );
				pxNumberControl->SetAnchors( ANCHORS_ALL_PARENT_RELATIVE );
				pxNumberControl->SetHasBorder( true );
				pxNumberControl->SetBorderWidth( 1.0f );
				pxNumberControl->SetNumberOnly( true );
				pxNumberControl->SetSingleLine( true );
			
				// Fill with init value
				char szValue[ 32 ];
				sprintf( szValue, "%f", pxExposedVariable->GetValue() );
				pxNumberControl->SetText( szValue );
			}
			break;
				
			// SLIDER /////////////////////////////////// 
			case EXPOSED_VARIABLE_SLIDER:
			{
				Slider* pxSliderControl = new Slider( pxParentPanel );
				pxSliderControl->SetName( pxExposedVariable->GetName() );
				pxSliderControl->SetPosition( s_pxControlPanel->GetOriginalX() + uEMPTYSPACE_MARGIN, s_uUserWidgetVerticalPos );
				pxSliderControl->SetSize( s_pxControlPanel->GetOriginalWidth() - uEMPTYSPACE_MARGIN * 2, 24);
				pxSliderControl->SetAnchors( ANCHORS_ALL_PARENT_RELATIVE );
			
				// Fill with init value
				pxSliderControl->SetValue( (float)pxExposedVariable->GetValue() );
			}
			break;
			
			// COLOUR WELL /////////////////////////////////// 
			case EXPOSED_VARIABLE_COLOUR:
			{
				ColourWell* pxColourWellControl = new ColourWell( pxParentPanel );
				pxColourWellControl->SetName( pxExposedVariable->GetName() );
				pxColourWellControl->SetPosition( s_pxControlPanel->GetOriginalX() + uEMPTYSPACE_MARGIN, s_uUserWidgetVerticalPos );
				pxColourWellControl->SetSize( s_pxControlPanel->GetOriginalWidth() - uEMPTYSPACE_MARGIN * 2, 24 );
				pxColourWellControl->SetAnchors( ANCHORS_ALL_PARENT_RELATIVE );
				pxColourWellControl->SetHasBorder( true );
				pxColourWellControl->SetBorderWidth( 1.0f );
				
				// Fill with init value
				pxColourWellControl->SetValue( static_cast< u_int >( pxExposedVariable->GetValue() ) );
			}
			break;
		}
		
		// Make label
		if( pxExposedVariable->GetShowLabel() )
		{
			s_uUserWidgetVerticalPos -= 17;
			StaticText* pxLabel = new StaticText( pxParentPanel );
			pxLabel->SetPosition( pxParentPanel->GetOriginalX() + uEMPTYSPACE_MARGIN, s_uUserWidgetVerticalPos );
			pxLabel->SetAnchors( ANCHORS_ALL_PARENT_RELATIVE );
			pxLabel->SetAutoSizes( true );
			pxLabel->SetText( pxExposedVariable->GetName() );
			s_uUserWidgetVerticalPos += 17;
		}
		
		s_uUserWidgetVerticalPos += 24 + uEMPTYSPACE_MARGIN;
	}
}

Widget* Controller_Screen_Editor::GetControlByName( const char* szTargetName )
{	
	TypedList<Widget>* pxControlPanelChildren = s_pxControlPanel->GetChildren();
	
	if ( !pxControlPanelChildren )
	{
		return NULL;
	}
	
	for (u_int i = 0; i < pxControlPanelChildren->Count(); i++)
	{
		Widget* tempPanel = pxControlPanelChildren->Get( i );
		Widget* tempWidget = tempPanel->GetChildren()->Get( 0 );
				
		if ( GetStringHash( tempWidget->GetName() ) == GetStringHash( szTargetName ) ) 
		{
			return tempWidget;
		}
	}
	return NULL;
}

void Controller_Screen_Editor::Menu_Preset_ResourceManager( void* pUserData )
{
}

void Controller_Screen_Editor::Menu_Fridge_New( void* pUserData )
{
	// TODO: Check if the preset is modified
	Controller_ModalDialog::SetCallback( Menu_Fridge_New_PostConfirmation );
	Controller_ModalDialog::Show( "Are you sure you want to create a new preset? (Changes will be lost)", DIALOGTYPE_YESNO );
}

void Controller_Screen_Editor::Menu_Fridge_New_PostConfirmation( Controller_ModalDialogResult eResult )
{
	if( eResult == DIALOGRESULT_YES )
	{
		Preset* pxPreset = Controller_Main::GetCurrentPreset();
		if( pxPreset )
		{
			pxPreset->Clear();
			pxPreset->Restart();
		}
		RecreateFromPreset();
	}
}

void Controller_Screen_Editor::Menu_Fridge_Open( void* pUserData )
{
	char szFileName[ FRIDGE_MAX_PATH ];
	
	if( FileTools::OpenPrompt( FRIDGE_FILE_PRESET, szFileName ) )
	{
		Preset* pxPreset = Controller_Main::GetCurrentPreset();
		if( pxPreset )
		{
			pxPreset->LoadFromFile( szFileName );
			pxPreset->Restart();
		}
		RecreateFromPreset();
	}
}

void Controller_Screen_Editor::Menu_Fridge_Save( void* pUserData )
{
	Preset* pxPreset = Controller_Main::GetCurrentPreset();
	if( pxPreset )
	{
		if( !pxPreset->GetFilename() )
		{
			Menu_Fridge_SaveAs( 0 );
		}
		else
		{
			pxPreset->SaveToFile( pxPreset->GetFilename() );
		}
	}
}

void Controller_Screen_Editor::Menu_Fridge_SaveAs( void* pUserData )
{
	char szFileName[ FRIDGE_MAX_PATH ];
	
	if( FileTools::SavePrompt( FRIDGE_FILE_PRESET, szFileName ) )
	{
		Preset* pxPreset = Controller_Main::GetCurrentPreset();
		if( pxPreset )
		{
			pxPreset->SaveToFile( szFileName );
		}
	}
}

void Controller_Screen_Editor::Menu_Fridge_MainMenu( void* pUserData )
{
	Controller_Main::ChangeScreen( CONTROLLER_SCREEN_MAIN );
}

void Controller_Screen_Editor::Menu_Fridge_Quit( void* pUserData )
{
	Controller_ModalDialog::SetCallback( Menu_Fridge_Quit_PostConfirmation );
	Controller_ModalDialog::Show( "Are you sure you want to quit?", DIALOGTYPE_YESNO );
}

void Controller_Screen_Editor::Menu_Fridge_Quit_PostConfirmation( Controller_ModalDialogResult eResult )
{
	if( eResult == DIALOGRESULT_YES )
	{
		Controller_Main::Quit();
	}
}

void Controller_Screen_Editor::Menu_Effect_SaveAsTemplate( void* pUserData )
{
	char szFile[ FRIDGE_MAX_PATH ];
	
	if( !FileTools::SavePrompt( FRIDGE_FILE_TEMPLATE, szFile ) )
	{
		return;
	}
	
	Preset* pxPreset = Controller_Main::GetCurrentPreset();
	if( pxPreset )
	{
		Element* pxElement = pxPreset->GetElement( s_pxTreeEditor->GetSelection() );
		if( pxElement )
		{
			pxElement->SaveToTemplateFile( szFile );
		}
	}
}

void Controller_Screen_Editor::RecreateFromPreset()
{
	// Recreate all controller elements based on the current preset
	
	// I NEED TO REWRITE THIS SORRY
	FAssert( false );

	/*s_pxTreeEditor->Clear();
	s_pxCodeEditor->Clear();
	s_pxScriptOutput->Clear();
	
	Preset* pxPreset = Controller_Main::GetCurrentPreset();
	if( pxPreset )
	{
		SuperTree<Element>* pxElements = pxPreset->GetElements();
		if( !pxElements )
		{
			return;
		}
		
		SuperTreeWalker<Element> xWalker( pxElements );
		while( !xWalker.Done() )
		{
			// TODO: This is a bit crap, need to:
			// 1) Make the setup for the tree editor entry shared with the stuff in Preset_EndDragDropCallback
			// 2) Make the tree editor take a parent handle so we can actually make a tree.. durr
			
			FHandle xHandle = xWalker.GetHandle();
			Element* pxElement = xWalker.Get( true );
			
			if( pxElement )
			{
				// Add to the tree editor control, use the same handle so that we have a mapping from preset to interface
				s_pxTreeEditor->InsertTreeItem( pxElement->GetName(), xHandle );
				
				TreeEditorEntry* pxEntry = s_pxTreeEditor->GetTreeItem( xHandle );
				pxEntry->SetImage( GetStringHash( "Star32" ) );
				pxEntry->SetUserCanDelete( true );
				pxEntry->SetUserCanDuplicate( true );
				s_pxTreeEditor->SetSelection( xHandle );
			}
		}
	}*/
}

// eof
